package be.idamf.flash.controls
{
	import be.idamf.flash.common.IDisposable;
	import be.idamf.flash.common.IInitializable;
	import be.idamf.flash.display.addBitmapOn;
	import be.idamf.flash.display.addShapeOn;
	import be.idamf.flash.display.autoDispose;
	import be.idamf.flash.display.autoInitialise;
	import be.idamf.flash.display.removeChildrenFrom;
	import be.idamf.flash.events.dispatchEventOn;
	import be.idamf.flash.exec.deferExec;
	
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Shape;
	import flash.display.Sprite;
	import flash.events.Event;
	
	[Event(name="change", type="flash.events.Event")]
	
	public class FrameSequence extends Sprite implements IInitializable, IDisposable
	{
		protected var _bitmap:Bitmap;
		protected var _steps:int;
		protected var _width:uint;
		protected var _height:uint;
		protected var _value:Number;
		protected var _direction:String;
		
		public function FrameSequence(width:uint = 32, height:uint = 32)
		{
			super();
			
			_width = width;
			_height = height;
			
			autoInitialise(this);
			autoDispose(this);
		}
		
		//////
		// Accessors
		
		[ChangeEvent("change")]
		public function get value():Number
		{
			return _value;
		}
		
		public function set value(value:Number):void
		{
			_value = value;
			invalidateDisplay();
			dispatchEventOn(this, Event.CHANGE);
		}
		
		public function set bitmapData(value:BitmapData):void
		{
			_bitmap.bitmapData = value;
			invalidateSize();
		}
		
		//////
		// Accessor Overrides
		
		override public function set width(value:Number):void
		{
			_width = value;
			invalidateSize();
			invalidateDisplay();
		}
		
		override public function set height(value:Number):void
		{
			_height = value;
			invalidateSize();
		}
		
		//////
		// IInitializable impl
		
		public function initialize():void
		{
			mask = addShapeOn(this);
			_bitmap = addBitmapOn(this);
			invalidateSize();
			invalidateDisplay();
		}
		
		//////
		// IDisposable impl
		
		public function dispose():void
		{
			removeChildrenFrom(this);
		}
		
		//////
		// Internal
		
		protected function invalidateSize():void
		{
			deferExec(this, resize);
		}
		
		protected function invalidateDisplay():void
		{
			deferExec(this, redraw);
		}
		
		protected function resize():void
		{
			with (Shape(mask).graphics)
			{
				clear();
				beginFill(0);
				drawRect(0, 0, _width, _height);
				endFill();
			}
			
			_direction = (_width == _bitmap.width ? "V" : "H");
			_steps = (_width == _bitmap.width ? _bitmap.height / _height : _bitmap.width / _width);
		}
		
		protected function redraw():void
		{
			var delta:int = (_value == 1 ? _steps - 1 : _value * _steps);
			_direction == "H" ?	(_bitmap.x = _width * delta) : (_bitmap.y = _height * delta);
		}
	}
}